package org.hagopa.games.moneypool.msgs;


import java.nio.ByteBuffer;

import org.hagopa.games.moneypool.msgs.ContentTypes.ChatMsg;
import org.hagopa.games.moneypool.msgs.ContentTypes.game.DiesThrow;
import org.hagopa.games.moneypool.msgs.ContentTypes.game.UpdateStatus;
import org.hagopa.games.moneypool.msgs.ContentTypes.service.ClientIntro;
import org.hagopa.games.moneypool.msgs.ContentTypes.service.EmptyContent;
import org.hagopa.games.moneypool.msgs.ContentTypes.service.PlayerType;
import org.hagopa.games.moneypool.msgs.ContentTypes.service.Version;

public class Message {
	
	
	private long sessionId = 0;		// actually an unsigned int
	private int clientId = 0;
	private CommandsEnum Command;
	private int contentSz = 0;
	private IMsgContent contentHandler = null;
	
	//private ByteBuffer msgHeader = null;
	
	
	 
	public long getSessionId() {
		return sessionId;
	}
	public void setSessionId(long sessionId) {
		this.sessionId = sessionId;
	}
	public int getClientId() {
		return clientId;
	}
	public void setClientId(int clientId) {
		this.clientId = clientId;
	}
	public CommandsEnum getCommand() {
		return this.Command;
	}
	public void setCommand(CommandsEnum command) {
		this.Command = command;
	}
	public int getContentSz() {
		return this.contentSz;
	}
	public void setContentSz(int contentSz) {
		this.contentSz = contentSz;
	}
	
	public IMsgContent getContentHandler() {
		return this.contentHandler;
	}
	public void setContentHandler(IMsgContent contentHandler) {
		this.contentHandler = contentHandler;
	}
	
	public byte[] marshall()
	{
		byte [] out = new byte[256];
		ByteBuffer msgHeader = ByteBuffer.allocate(256);
		
		msgHeader.putInt(this.clientId);
//@TPAZ - send unsigned-int over 'long' - Begin
//		msgHeader.putLong(this.sessionId);
		byte [] bbuf = new byte[4];

		bbuf[0] = (byte) ((this.sessionId & 0xFF000000L) >> 24);
		bbuf[1] = (byte) ((this.sessionId & 0x00FF0000L) >> 16);
		bbuf[2] = (byte) ((this.sessionId & 0x0000FF00L) >> 8);
		bbuf[3] = (byte) (this.sessionId & 0x000000FFL);
		
		msgHeader.put(bbuf[0]);
		msgHeader.put(bbuf[1]);
		msgHeader.put(bbuf[2]);
		msgHeader.put(bbuf[3]);
//@TPAZ - send unsinged-int over 'long' - End
		
		msgHeader.putInt(this.Command.idx());
		msgHeader.putInt(this.contentSz);
		if(null != this.contentHandler)
		{
			System.out.println("Content is empty");
			byte [] tmp = contentHandler.marshallToByte();
			if(null == tmp)
			{
				System.out.println("TMP null");
				return null;
			}
			System.out.println("First elem: " + tmp[0] + " size: " + contentHandler.getSize());
			msgHeader.put(tmp, 0, contentHandler.getSize());
			
			//return null;
		}
		msgHeader.rewind();
		//msgHeader.order(ByteOrder.BIG_ENDIAN);
		msgHeader.get(out, 0, out.length);
		return out;
	}
	
	public boolean unmarshall(byte [] data)
	{
		if(null == data)
		{
			System.out.println("Empty Data array");
			return false;
		}
		
		ByteBuffer lmsgHeader = ByteBuffer.wrap(data);
		if(null == lmsgHeader)
			return false;
		
		
		this.clientId = lmsgHeader.getInt();
//@TPAZ - Recieve unsigned-int into 'long' - Begin
//		this.sessionId = lmsgHeader.getLong();
		int firstByte = 0;
        int secondByte = 0;
        int thirdByte = 0;
        int fourthByte = 0;

      //  int index = 4;
        
        firstByte = (0x000000FF & ((int)lmsgHeader.get()));
        secondByte = (0x000000FF & ((int)lmsgHeader.get()));
        thirdByte = (0x000000FF & ((int)lmsgHeader.get()));
        fourthByte = (0x000000FF & ((int)lmsgHeader.get()));
        
    

        // cast into our Long type
        this.sessionId = ((long) (firstByte << 24
                	| secondByte << 16
                    | thirdByte << 8
                    | fourthByte))
                   & 0xFFFFFFFFL;

//@TPAZ - Recieve unsigned-int into 'long' - End
        int cmdTmp = lmsgHeader.getInt();
        System.out.println("Received Command: " + cmdTmp);
        if((10 < cmdTmp) && cmdTmp< 1000)
        {
        	this.Command = CommandsEnum.getEnum(cmdTmp);
        	System.out.println("Command name:" + this.Command.getName());
        	if(null == this.Command)
        	{
        		System.out.println("Unknown Command!!!");
        		return false;
        	}
        }
        else
        {
        	System.out.println("Unknown Command!!!");
        	return false;
        }
		
		this.contentSz = lmsgHeader.getInt();
		if(this.contentSz > 0)
		{
			byte [] content = new byte[lmsgHeader.remaining()];
			if(null == content || content.length < 2)
			{
				this.contentHandler = new EmptyContent();
			}
			else
			{
				switch(this.Command){
				case SERV_HELLO:
					this.contentHandler = new Version();
					lmsgHeader.get(content, 0, content.length);
					this.contentHandler.unmarshallFromByte(content);
					break;
				case INTRO:
					this.contentHandler = new ClientIntro();
					lmsgHeader.get(content, 0, content.length);
					this.contentHandler.unmarshallFromByte(content);
					break;
				
				case READY:
					this.contentHandler = new PlayerType();
					lmsgHeader.get(content, 0, content.length);
					this.contentHandler.unmarshallFromByte(content);
					break;
				case UPDATE:
					this.contentHandler = new UpdateStatus();
					lmsgHeader.get(content, 0, content.length);
					this.contentHandler.unmarshallFromByte(content);
					break;
//				case STATUS:
//					this.contentHandler = new StatusData();
//					lmsgHeader.get(content, 0, content.length);
//					this.contentHandler.unmarshallFromByte(content);
//					break;
				case THR_DIES:
					this.contentHandler = new DiesThrow();
					lmsgHeader.get(content, 0, content.length);
					this.contentHandler.unmarshallFromByte(content);
					break;
				case MOVE_DONE:
	////merde!!!!!!!	
					this.contentHandler = new EmptyContent();
					lmsgHeader.get(content, 0, content.length);
					this.contentHandler.unmarshallFromByte(content);
					break;
				case CHAT_MSG:
					this.contentHandler = new ChatMsg();
					((ChatMsg)this.contentHandler).setTotal_size(this.contentSz);
					lmsgHeader.get(content, 0, this.contentSz);
					this.contentHandler.unmarshallFromByte(content);
					break;
					
				default:
						System.out.println("Unknown data");
					return false;
				}
			}
		}
		return true;
	}
	
}
